package JMH.day03.atomicboolean;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 实现一个TryLock锁，可以立即返回并退出阻塞的显示锁。
 * 改方法与synchronize相比，可以获取到锁当前的状态
 */
public class TryLock {

    private final AtomicBoolean flag = new AtomicBoolean(false); // 初始化flag

    private final ThreadLocal<Boolean> threadLocal = ThreadLocal.withInitial(() -> false); // 线程保险箱,存放线程与上下文关联的数据副本

    // 立即返回锁的状态
    public boolean lock() {
        // 使用CAS操作对flag进行修改，只有预期值为false的时候才能操作成功
        boolean cas = flag.compareAndSet(false, true);
        if (cas) { // 根据cas修改成功与否，对线程保险箱进行修改
            threadLocal.set(true);
        }
        return cas;
    }

    /**
     * 锁的释放
     * 一般为了确保锁的释放，都会放在try...finally方法中进行，所以，
     * 为了避免多线程情况下，执行释放锁操作的时候，并没有获得锁权限的线程错误的释放锁，
     * 使用ThreadLocal作为保险箱，来进行线程的权限校验
     */
    public boolean release() {

        if (threadLocal.get()) { // 判断是否加锁，如果加锁则释放锁，并返回释放结果，没有加锁则返回false
            threadLocal.set(false);
            return flag.compareAndSet(true, false);
        }
        return false;
    }

}
